const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
puppeteer.use(StealthPlugin());
const dayjs = require("dayjs");
const axios = require("axios");
const userDataDir = process.env.WEB_CONFIG_USER_DATA_DIR;
const executablePath = process.env.WEB_CONFIG_EXECUTABLE_PATH;
const TOUTIAOHAO_USERNAME = process.env.TOUTIAOHAO_USERNAME;
const TOUTIAOHAO_PASSWORD = process.env.TOUTIAOHAO_PASSWORD;
const userAgent = process.env.USER_AGENT;
const logger = require("../../utils/logger");
const fs = require("fs");
const path = require("path");

const { saveMysql } = require("../../utils/saveMysql");

async function getArticlesInfo(params) {
  let results = []; // 确保在这里定义 results 数组
  const browser = await puppeteer.launch({
    headless: "new",
    headless: false,
    userDataDir,
    executablePath,
    defaultViewport: null,
    args: [
      "--no-sandbox",
      "--disable-setuid-sandbox",
      "--disable-features=site-per-process",
      "--start-maximized",
    ],
    ignoreHTTPSErrors: true,
  });

  try {
    const page = await browser.newPage();
    await page.setUserAgent(userAgent);

    const dimensions = await page.evaluate(() => ({
      width: window.innerWidth,
      height: window.innerHeight,
    }));
    await page.setViewport(dimensions);

    await page.goto("https://mp.toutiao.com/profile_v4/manage/content/all", {
      waitUntil: "networkidle2",
    });

    if (await isNotLogin(page)) {
      logger.info("未登录，开始登录流程...");
      try {
        await login(page);
        logger.info("登录成功");
      } catch (error) {
        logger.error(`登录失败: ${error.message}`);
        throw error;
      }
    }
    logger.info("已登录");
    await page.waitForSelector(".user-auth-avator");
    //筛选符合的日期数据
    await setCorrectDate(params, page);
    await new Promise((resolve) => setTimeout(resolve, 5000));
    //获取列表，点击查看数据，依次点击下一页直至最后一页
    results = await getArticleList(page, results);
    return results;
  } catch (error) {
    logger.error(`发生错误: ${error.message}`);
    return [];
  } finally {
    //await browser.close(); // 确保关闭浏览器
  }
}

// 辅助函数: 检查是否登录
async function isNotLogin(page) {
  try {
    const loginButton = await page.$(".web-login-button");
    return loginButton !== null;
  } catch (error) {
    logger.error(`检查登录状态时发生错误: ${error.message}`);
    return true;
  }
}

// 将日期筛选为符合条件的日期
async function setCorrectDate(params, page) {
  const startDate = getStartDate(params);
  const endDate = params.end_date
    ? params.end_date
    : dayjs().format("YYYY-MM-DD");
  //获取开始日期input
  const startDateInput = await page.$(
    "input[class='byte-rangepicker-input-start-time']"
  );
  //获取结束日期input
  const endDateInput = await page.$(
    "input[class='byte-rangepicker-input-end-time']"
  );
  //设置开始日期
  await startDateInput.type(startDate, { delay: 100 });
  await new Promise((resolve) => setTimeout(resolve, 1500));
  //设置结束日期
  await endDateInput.type(endDate, { delay: 100 });
  //填完日期后，页面会自动请求，等待请求结束
  await page.waitForResponse((response) => {
    return response
      .url()
      .includes("https://mp.toutiao.com/api/feed/mp_provider/v1/");
  });
  logger.info(`${startDate}到${endDate}的请求结束`);
}
function getStartDate(params) {
  if (params.update_type === "highFrequency") {
    return dayjs().subtract(7, "day").format("YYYY-MM-DD");
  } else if (params.interval) {
    return dayjs()
      .subtract(parseInt(params.interval), "day")
      .format("YYYY-MM-DD");
  }
  return dayjs("2024-01-01").format("YYYY-MM-DD");
}
// 登录逻辑
async function login(page) {
  await page.click("li[aria-label='账密登录']");
  await new Promise((resolve) => setTimeout(resolve, 1000));
  await page.click("span.web-login-confirm-info__checkbox");
  await new Promise((resolve) => setTimeout(resolve, 1000));
  await typeSlowly(
    page,
    "div.web-login-normal-input input[name='normal-input']",
    TOUTIAOHAO_USERNAME
  );
  await new Promise((resolve) => setTimeout(resolve, 1000));
  await typeSlowly(
    page,
    "div.web-login-button-input input[name='button-input']",
    TOUTIAOHAO_PASSWORD
  );
  await new Promise((resolve) => setTimeout(resolve, 1000));
  await page.click(".web-login-button");
  // await page.waitForNavigation({ waitUntil: "networkidle0", timeout: 600000 });
  await page.waitForSelector(".user-auth-avator", { timeout: 600000 });
}

// 新增函数：慢速输入文本
async function typeSlowly(page, selector, text) {
  const el = await page.$(selector);
  if (!el) throw new Error(`未找到元素: ${selector}`);
  for (let char of text) {
    await el.type(char, { delay: 100 + Math.random() * 200 });
    await new Promise((resolve) =>
      setTimeout(resolve, 50 + Math.random() * 100)
    );
  }
}
// 获取列表，点击 span 内容为 查看数据，依次点击下一页直至最后一页
async function getArticleList(page, results, currentPage = 1) {
  const articleList = await page.$$(".genre-item");
  logger.info(`找到第 ${currentPage} 页 ${articleList.length} 篇文章`);

  for (const article of articleList) {
    try {
      const viewDataButton = await page.evaluateHandle((el) => {
        const spans = el.querySelectorAll("*");
        return Array.from(spans).find(
          (span) => span.textContent.trim() === "查看数据"
        );
      }, article);
      if (viewDataButton) {
        const promiseResponse = new Promise((resolve) => {
          page.on("response", async (response) => {
            if (
              response
                .url()
                .includes(
                  "https://mp.toutiao.com/mp/agw/statistic/v2/item/info"
                )
            ) {
              const _detailData = await response.json();
              resolve(_detailData);
            }
          });
        });
        await new Promise((resolve) => setTimeout(resolve, 2000));
        await viewDataButton.click();
        try {
          const detailData = await promiseResponse;
          if (!detailData || detailData.code !== 0) {
            logger.error("详情数据为空或请求失败");
            return;
          }
          const itemData = detailData.item_data;
          const itemStat = itemData.item_stat;
          // #TAG: 需要多种文章类型，验证详情地址拼接
          let detail_urls = {
            1: "https://www.toutiao.com/article/",
            2: "https://www.toutiao.com/video/",
            3: "https://www.toutiao.com/w/",
            4: "https://www.toutiao.com/answer/",
            5: "https://www.toutiao.com/video/",
          };
          // 将数据存储到对象中
          const dataObject = {
            title: itemData.title,
            id: itemData.item_id,
            cover: JSON.stringify(
              itemData.cover_url ? [itemData.cover_url] : []
            ),
            detail_url: detail_urls[itemData.genre_type]
              ? detail_urls[itemData.genre_type] + itemData.item_id
              : "联系前端补充类型",
            genre_type: itemData.genre_type,
            publish_time: dayjs
              .unix(itemData.create_time)
              .format("YYYY-MM-DD HH:mm:ss"),
            recommend_count: itemStat.consume_data.impression_count,
            read_count:
              itemStat.consume_data.go_detail_count === -1
                ? itemStat.consume_data.play_count
                : itemStat.consume_data.go_detail_count,
            comment_count: itemStat.interaction_data.comment_count,
            like_count: itemStat.interaction_data.digg_count,
            forward_count: itemStat.interaction_data.forward_count,
            share_count: itemStat.interaction_data.share_count,
            collect_count: itemStat.interaction_data.repin_count,
          };
          // 将对象添加到结果数组中
          results.push(dataObject);
          // 打印文章第几页，第几条，标题，日期
          logger.info(
            `第 ${currentPage} 页，第 ${results.length} 条，标题：${itemData.title
            }, 日期：${dayjs
              .unix(itemData.create_time)
              .format("YYYY-MM-DD HH:mm:ss")}`
          );
        } catch (error) {
          logger.error(`获取详情数据时出错: ${error.message}`);
        }
      } else {
        logger.info('未找到"查看数据"按钮');
      }
    } catch (error) {
      logger.error(`处理文章时出错: ${error.message}`);
    } finally {
      // 等待一段时间，避免操作过快
      await new Promise((resolve) => setTimeout(resolve, 2500));
      await page.evaluate(() => {
        const closeButton = document.querySelector(".byte-drawer-close-icon");
        if (closeButton) {
          closeButton.click();
        }
      });
      await new Promise((resolve) => setTimeout(resolve, 500));
    }
  }

  // 检查是否有下一页，如果有则点击并继续获取文章列表
  try {
    const nextPageButton = await page.$(
      ".fake-pagination-item-icon:not(.disabled) .byte-icon-right"
    );
    if (nextPageButton) {
      await nextPageButton.click();
      logger.info("点击下一页");
      await new Promise((resolve) => setTimeout(resolve, 2000)); // 等待页面加载
      // 递归调用时也传递 results 数组
      return await getArticleList(page, results, currentPage + 1);
    } else {
      logger.info("没有下一页了");
    }
  } catch (error) {
    logger.error("处理翻页时出错:", error.message);
  }

  return results; // 返回收集到的所有结果
}
//---------------------------------------------------------------头条号发布开始---------------------------------------------------------------//
async function publish(params) {
  const browser = await puppeteer.launch({
    headless: false,
    userDataDir,
    executablePath,
    defaultViewport: null,
    args: [
      "--no-sandbox",
      "--disable-setuid-sandbox",
      "--disable-features=site-per-process",
      "--start-maximized",
      // "--auto-open-devtools-for-tabs",
    ],
  });

  try {
    const page = await browser.newPage();
    await page.setUserAgent(userAgent);

    const dimensions = await page.evaluate(() => ({
      width: window.innerWidth,
      height: window.innerHeight,
    }));
    await page.setViewport(dimensions);

    await page.goto("https://mp.toutiao.com/profile_v4/manage/content/all", {
      waitUntil: "networkidle2",
    });

    if (await isNotLogin(page)) {
      logger.info("未登录，开始登录流程...");
      try {
        await login(page);
        logger.info("登录成功");
      } catch (error) {
        logger.error(`登录失败: ${error.message}`);
        throw error;
      }
    }
    logger.info("已登录");
    await page.waitForSelector(".user-auth-avator");
    // 进入视频发布页面
    await page.goto("https://mp.toutiao.com/profile_v4/xigua/upload-video", {
      waitUntil: "networkidle2",
    });
    logger.info("已进入视频发布页面");

    // 下载视频和封面文件
    await downloadFiles(params);

    // 上传视频和封面
    await uploadFiles(page, params);

    // 输入标题
    logger.info(`开始输入标题: ${params.title}`);
    // 直接替换input内容
    // await page.evaluate((title) => {
    //   const input = document.querySelector(".article-title-wrap input");
    //   if (input) {
    //     input.value = title;
    //   }
    // }, params.title);
    const inputSelector = ".article-title-wrap input";
    await page.click(inputSelector, { clickCount: 3 }); // 选中所有文本
    await page.keyboard.press("Backspace"); // 删除选中的文本
    await page.type(inputSelector, params.title, { delay: 100 }); // 输入新标题
    await new Promise((resolve) => setTimeout(resolve, 1000));
    // 输入简介summary
    try {
      await page.type(".video-form-item-wrapper textarea", params.summary || "", {
        delay: 100,
      });
    } catch (err) {

    }

    // 输入话题
    logger.info(`开始输入话题: ${params.talk}`);
    await handleTopics(page, params.talk);

    // 视频生成图文
    await handleVideo2art(page, params.video2art);

    // 点击发布按钮
    await page.click('.video-batch-footer button[class*="submit"]');
    // 等待发布完成
    await page.waitForResponse((response) =>
      response
        .url()
        .includes("https://mp.toutiao.com/xigua/api/upload/PublishVideo")
    );
    console.log('发布成功')
    return {
      success: true,
      message: "发布成功",
      id: "",
    };

  } catch (error) {
    logger.error(`发布视频时发生错误: ${error.message}`);
    return {
      success: false,
      message: "发布失败: " + error.message,
    };
  } finally {
    //await browser.close();
  }
}
// https://mp.toutiao.com/profile_v4/xigua/upload-video

async function downloadFiles(params) {
  logger.info(`开始下载文件: ${params.title}`);
  const date = dayjs().format("YYYY-MM-DD");
  const dir = path.join(__dirname, `../uploads/toutiaohao/${date}`);
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }

  if (params.video) {
    logger.info(`开始下载视频: ${params.video}`);
    const videoName = path.basename(new URL(params.video).pathname);
    const videoPath = path.join(dir, videoName);
    await downloadFile(params.video, videoPath);
    params.video = videoPath;
    logger.info(`视频下载成功，地址：${videoPath}`);
  }

  if (params.cover) {
    logger.info(`开始下载封面: ${params.cover}`);
    const coverName = path.basename(new URL(params.cover).pathname);
    const coverPath = path.join(dir, coverName);
    await downloadFile(params.cover, coverPath);
    params.cover = coverPath;
    logger.info(`封面下载成功，地址：${coverPath}`);
  }

  logger.info(`所有文件下载完成`);
}

async function downloadFile(url, path) {
  const response = await axios({
    method: "GET",
    url,
    responseType: "stream",
  });
  return new Promise((resolve, reject) => {
    const stream = fs.createWriteStream(path);
    response.data.pipe(stream);
    stream.on("finish", () => {
      resolve();
    });
    stream.on("error", (error) => {
      reject(error);
    });
  });
}

async function uploadFiles(page, params) {
  logger.info(`开始上传文件: ${params.title}`);
  try {
    // 上传视频
    const videoInput = await page.$(
      '.upload-video-trigger input[type="file"][accept*="mp4"]'
    );
    await videoInput.uploadFile(params.video);

    // 等待视频上传完成, 最长等待15分钟
    await page.waitForResponse(
      (response) => {
        const url = response.url();
        if (url.startsWith("https://vod.bytedanceapi.com/")) {
          const urlObj = new URL(url);
          return urlObj.searchParams.get("Action") === "CommitUploadInner";
        }
        return false;
      },
      { timeout: 600000 }
    );
    logger.info("视频上传成功");

    // 上传封面（如果有）
    if (params.cover) {
      // 点击上传封按钮
      // mouse move .xigua-poster-editor element and click it
      // scroll to .xigua-poster-editor element
      await page.evaluate(() => {
        const editor = document.querySelector(".xigua-poster-editor");
        if (editor) {
          editor.scrollIntoView();
        }
      });
      await new Promise((resolve) => setTimeout(resolve, 1000));
      await page.click(".xigua-poster-editor");
      await page.waitForSelector(".Dialog-container", { visible: true });
      await new Promise((resolve) => setTimeout(resolve, 1000));
      // 点击本地上传，切换到上传封面
      await page.evaluate(() => {
        const tabs = document.querySelectorAll(".Dialog-container .header li");
        Array.from(tabs).forEach((tab) => {
          if (tab.textContent.includes("本地上传")) {
            tab.click();
            return;
          }
        });
      });
      await uploadCover(page, params.cover);
      // 点击 完成裁剪
      logger.info("开始点击是否， 完成裁剪");
      try {
        await page.click(".Dialog-container .clip-btn-content");
        await new Promise((resolve) => setTimeout(resolve, 1000));
      } catch (error) {
        logger.info(`图片合规，不需要裁剪`);
      }
      logger.info("确认裁剪");
      await page.click(".Dialog-container .footer-btns .btn-sure");
      await new Promise((resolve) => setTimeout(resolve, 1000));
      logger.info("开始上传");
      await page.click(".Dialog-container .footer button.red");
      await page.waitForResponse(
        (response) => {
          const url = response.url();
          return url.includes(
            "https://mp.toutiao.com/xigua/api/upload/GetImgUrl/"
          );
        },
        { timeout: 600000 }
      );
      logger.info("完成封面裁剪并上传");
    }

    logger.info("所有文件上传完成");
  } catch (error) {
    logger.error(`上传文件时发生错误: ${error.message}`);
    throw error;
  }
}
// 上传封面
async function uploadCover(page, coverPath) {
  logger.info(`开始上传封面: ${coverPath}`);
  const coverInput = await page.$(
    '.xigua-upload-poster-trigger input[type="file"][accept*="image"]'
  );
  await coverInput.uploadFile(coverPath);
  await page.waitForResponse((response) => {
    const url = response.url();
    return url.includes("https://mp.toutiao.com/xigua/api/upload/GetImgUrl/");
  });
  await new Promise((resolve) => setTimeout(resolve, 1000));
  logger.info("封面上传成功");
}
// 话题
async function handleTopics(page, topics) {
  logger.info(`开始添加话题: ${topics}`);
  if (!topics || topics.length === 0) {
    logger.info("没有话题");
    return;
  }
  try {
    for (const topic of topics) {
      await page.focus(".form-item-hash_tag input");
      await page.keyboard.type(topic, { delay: 100 });
      await new Promise((resolve) => setTimeout(resolve, 1000));
      await page.keyboard.press("Enter");
    }
  } catch (err) {

  }

}
// 视频生成图文
async function handleVideo2art(page, status) {
  logger.info(`是否生成图文：${status}`);
  if (status != 1 && status != 0) {
    return;
  }
  // 取消全选
  await page.evaluate(() => {
    const checkboxs = document.querySelectorAll(
      '.form-item-video2art input[type="checkbox"]'
    );
    Array.from(checkboxs).forEach((item) => {
      if (item.checked) {
        item.click();
      }
    });
  });

  // 选择生成图文
  if (status == 1) {
    logger.info("择生成图文");
    await page.evaluate(() => {
      const checkboxs = document.querySelectorAll(
        '.form-item-video2art input[type="checkbox"]'
      );
      Array.from(checkboxs).forEach((item) => {
        item.click();
      });
    });
  }
}

//---------------------------------------------------------------头条号发布结束---------------------------------------------------------------//

exports.handleCommand = async (command, params, taskId) => {
  switch (command) {
    case "getArticlesInfo":
      const data = await getArticlesInfo(params);
      console.log(data);
      saveToutiaohao2Mysql(data);
      return { data };
    case "publish":
      try {
        const result = await publish(params);
        if (result.success) {

          return {
            data: [
              {
                ...result,
              },
            ],
          };
        } else {
          throw new Error(result.message);
        }
      } catch (error) {
        logger.error(`发布文章时发生错误: ${error.message}`);

        return {
          data: [
            {
              success: false,
              message: error.message,
            },
          ],
        };
      }
    default:
      throw new Error("不支持的命令");
  }
};

const saveToutiaohao2Mysql = async (data) => {
  try {
    // 确保data是数组
    if (!Array.isArray(data)) {
      logger.error('输入数据不是数组格式');
      return;
    }

    for (const item of data) {
      // 验证必要字段
      if (!item.id) {
        logger.error('缺少必要字段 id，跳过该条数据');
        continue;
      }

      if (item.genre_type == 3) {
        logger.info(`跳过头条号文章 ${item.id}`);
        continue;
      }
      const saveData = {
        // 平台标识，固定为"toutiaohao"
        platform: "toutiaohao",
        // 视频唯一标识ID
        aweme_id: item.id,
        // 视频创建时间，转换为unix时间戳
        create_time: item.publish_time ? dayjs(item.publish_time).unix() : dayjs().unix(),
        // 数据爬取时间
        crawl_time: dayjs().format('YYYY-MM-DD HH:mm:ss'),

        // 视频基本信息
        video_desc: item.desc || '',
        video_url: item.detail_url ? item.detail_url : '',
        // 解析JSON字符串获取第一个封面URL，如果解析失败则使用空字符串
        cover_url: (() => {
          try {
            const covers = JSON.parse(item.cover);
            return Array.isArray(covers) && covers.length > 0 ? covers[0] : '';
          } catch (e) {
            logger.warn(`解析视频 ${item.id} 的封面URL失败: ${e.message}`);
            return '';
          }
        })(),

        // 统计数据
        play_count: item.statistics?.play_count || 0,
        digg_count: item.statistics?.digg_count || 0,
        comment_count: item.statistics?.comment_count || 0,
        download_count: item.statistics?.download_count || 0,
        forward_count: item.statistics?.forward_count || 0,
        share_count: item.statistics?.share_count || 0,

        // 以下是必需字段但API未提供的数据，设置默认值
        author_uid: item.author?.uid || '',
        author_sec_uid: item.author?.sec_uid || '',
        author_nickname: item.author?.nickname || '',
        author_signature: item.author?.signature || '',
        author_avatar_url: item.author?.avatar_thumb?.url_list[0] || '',
        author_following_count: item.author?.following_count || 0,
        author_follower_count: item.author?.follower_count || 0,
        author_total_favorited: item.author?.total_favorited || 0,
        author_unique_id: item.author?.unique_id || '',
        duration: item.video?.duration || 0,
        width: item.video?.width || 0,
        height: item.video?.height || 0,
        music_id: item.music?.id || '',
        music_title: item.music?.title || '',
        music_author: item.music?.author || '',
        music_duration: item.music?.duration || 0,
        hashtags: JSON.stringify(item.text_extra?.map(tag => ({
          hashtag_name: tag.hashtag_name,
          hashtag_id: tag.hashtag_id
        })) || [])
      };

      logger.info(`正在保存头条视频 ${item.id} 的数据`);
      await saveMysql(saveData);

      // 添加延迟避免请求过快
      await new Promise(resolve => setTimeout(resolve, 1000));
    }

    logger.info(`数据保存完成，共处理 ${data.length} 条记录`);
  } catch (error) {
    logger.error(`保存数据时发生错误: ${error.message}`);
    throw error;
  }
};
